package com.tang.qzzp.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.github.pagehelper.PageInfo;
import com.tang.qzzp.entity.Text;
import com.tang.qzzp.entity.User;
import com.tang.qzzp.service.TextService;
import com.tang.qzzp.service.UserService;
import com.tang.qzzp.utils.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpSession;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @Author 唐海清
 * @Version V1.0
 * @Description 该Controller执行常见Ajax脚本
 */
@Controller
@RequestMapping("/ajax")
@Slf4j(topic = "AjaxController")
public class AjaxController {
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private TextService textService;
    @Resource
    private UserService userService;
    @Resource
    private MailUtil mailUtil;

    /**
     * 插入文本内容 联合定时器使用
     *
     * @param textArticle 文本内容
     */
    @GetMapping("/insertText/{textArticle}")
    @ResponseBody
    public void insertText(@PathVariable("textArticle") String textArticle) {
        try {
            log.info("文本内容为　: {}", textArticle);
            Text text = new Text();
            String id = UUID.randomUUID().toString();
            text.setId(id);
            text.setTextArticle(textArticle);
            textService.save(text);
            log.info("插入文本成功!");
        } catch (Exception e) {
            log.error("exception : {}", e.getMessage());
        }
    }

    /**
     * index.html加载时所触发的函数 -- 获取文本内容
     * 首先获取Redis缓存中的文本内容,若无则添加，有则直接读取
     *
     * @return JSON
     */
    @PostMapping("/getTexts")
    @ResponseBody
    public String getTexts() {
        log.info("开始获取首页文本 : {}", TimeUtil.getCurrentTime());
        int textNumbers = (int) textService.count();
        Random random = new Random();
        int count = random.nextInt(textNumbers);
        log.info("获取的文本次序为 : {}", count);
        Object o = redisUtil.get(StringUtil.TEXT_PREFIX + count);
        if (o != null) {
            String json = JSON.toJSONString(o);
            log.info("获取Redis缓存中文本内容 : {}", json);
            log.info("获取首页文本结束 : {}", TimeUtil.getCurrentTime());
            return json;
        } else {
            Text text = textService.getById(count);
            String json = JSONObject.toJSONString(text);
            log.info("获取Redis缓存中文本内容 : {}", json);
            redisUtil.set(StringUtil.TEXT_PREFIX + count, json, 300L, TimeUnit.SECONDS);
            log.info("获取首页文本结束 : {}", TimeUtil.getCurrentTime());
            return json;
        }
    }

    /**
     * 跳转登陆页面
     */
    @GetMapping("/toLogin")
    public String toLogin(Model model) {
        log.info("前往登陆页面~");
        model.addAttribute("userName", ShiroUtil.getUserName());
        return "login";
    }

    /**
     * 登陆逻辑：  使用MD5工具和Shiro
     *
     * @param userName     用户名
     * @param userPassword 用户密码
     * @param rememberMe   记住我
     * @return 返回登陆结果
     */
    @PostMapping("/login")
    @ResponseBody
    public String login(@RequestParam("userName") String userName, @RequestParam("userPassword") String userPassword, @RequestParam("rememberMe") boolean rememberMe, HttpSession session) {
        //将用户输入的密码进行盐值加密
        String loginMsg;
        Map<String, Object> resultMap = new HashMap<>(16);
        User user = userService.getOne(new QueryWrapper<User>().eq("user_name", userName));
        if (user == null) {
            loginMsg = "账户名或密码错误!!!";
        } else {
            boolean flag = Md5Util.validPassword(userPassword, user.getUserPassword());
            log.info("用户输入的密码是否为匹配盐值加密的密码 : {}", flag);
            if (flag) {
                if (user.getUserStatus() != 1) {
                    log.info("登陆用户名 : {}", userName);
                    log.info("用户是否需要记住密码 :{}", rememberMe);
                    UsernamePasswordToken token = new UsernamePasswordToken(userName, user.getUserPassword(), rememberMe);
                    token.setRememberMe(rememberMe);
                    ShiroUtil.login(token);
                    User currentUser = ShiroUtil.getCurrentUser();
                    session.setAttribute("user", currentUser);
                    loginMsg = "登陆成功";
                } else {
                    loginMsg = "请先完成激活";
                }
            } else {
                loginMsg = "账户名或密码错误!!!";
            }
        }
        resultMap.put("login_msg", loginMsg);
        String json = JSON.toJSONString(resultMap);
        log.info("返回的JSON数据 : {}", json);
        return json;
    }

    /**
     * 退出当前用户
     */
    @GetMapping("/exit")
    public String exit() {
        User currentUser = ShiroUtil.getCurrentUser();
        ShiroUtil.exit();
        log.info(currentUser.getUserName() + "已经退出登陆");
        return "index";
    }

    /**
     * @return 跳转注册页面
     */
    @GetMapping("/toRegister")
    public String toRegister(Model model) {
        log.info("跳转注册页面");
        model.addAttribute("userName", ShiroUtil.getUserName());
        return "register";
    }

    /**
     * 检测用户名是否存在
     *
     * @param userName 用户名
     * @return String
     */
    @PostMapping("/checkUsernameIsRepeat")
    @ResponseBody
    public boolean checkUsernameIsRepeat(@RequestParam("userName") String userName) {
        log.info("注册的用户名为 : {}", userName);
        boolean result = false;
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_name", userName);
        User user = userService.getOne(wrapper);
        if (user != null) {
            result = true;
        }
        log.info("检查用户名是否重复 : {}", result);
        return result;
    }

    /**
     * 用户注册
     *
     * @return 返回注册结果
     */
    @PostMapping("/register")
    @ResponseBody
    public Map<String, Object> register(@RequestParam("userName") String userName, @RequestParam("userPassword") String userPassword, @RequestParam("userEmail") String userEmail) {
        Map<String, Object> resultMap = new HashMap<>(16);
        String userId = UUID.randomUUID().toString();
        userPassword = Md5Util.getEncryptedPwd(userPassword);
        log.info("MD5加密后的密码");

        User user = new User();
        user.setUserId(userId);
        user.setUserName(userName);
        user.setUserPassword(userPassword);
        user.setUserEmail(userEmail);
        user.setUserStatus(1);
        user.setCreateTime(TimeUtil.getCurrentTime());
        user.setUpdateTime(TimeUtil.getCurrentTime());
        user.setVersion(1);
        user.setDeleted(0);

        //此时进行判断处理  如果Redis缓存中已有该邮箱信息，给出相应提示
        Object registerMessage = redisUtil.get(StringUtil.REGISTER_PREFIX + userEmail);
        if (registerMessage == null || registerMessage == "") {
            userService.save(user);
            //当前用户未使用该邮箱进行注册
            if (mailUtil.sendMail(userEmail)) {
                //邮件发送成功
                log.info("邮件发送成功!");
                resultMap.put("register_message", "200");
            } else {
                log.info("邮件发送失败!");
                resultMap.put("register_message", "400");
            }
        } else {
            log.info("邮件发送失败!(Redis缓存已经存在该邮箱)");
            resultMap.put("register_message", "500");
        }
        return resultMap;
    }

    /**
     * 一个用户只能有唯一一个邮箱
     *
     * @param userEmail 用户邮箱
     * @return boolean
     */
    @PostMapping("/checkUserEmailIsRepeat")
    @ResponseBody
    public boolean checkUserEmailIsRepeat(@RequestParam("userEmail") String userEmail) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("user_email", userEmail);
        return userService.getOne(wrapper) != null;
    }

    /**
     * 用户凭借激活码激活
     *
     * @param activeCode 激活码
     * @return Map<String, Object>
     */
    @RequestMapping("/activeUser")
    @ResponseBody
    public Map<String, Object> activeUserByCode(@RequestParam("activeCode") String activeCode,
                                                @RequestParam("userEmail") String userEmail) {
        Map<String, Object> resultMap = new HashMap<>(16);
        String key = StringUtil.REGISTER_PREFIX + userEmail;
        String value = (String) redisUtil.get(key);
        if (value.isEmpty()) {
            log.info("redis缓存中无该激活码！");
            resultMap.put("result_msg", "请重新注册您的账户！");
        } else {
            //检查输入激活码是否与redis缓存中匹配
            if (!activeCode.equalsIgnoreCase(value)) {
                log.info("激活码不匹配！");
                resultMap.put("result_msg", "激活码不匹配！");
            } else {
                QueryWrapper<User> wrapper = new QueryWrapper<>();
                wrapper.eq("user_email", userEmail);
                User activeUser = userService.getOne(wrapper);
                if (activeUser != null) {
                    //立即删除redis缓存并更新用户状态
                    activeUser.setUserStatus(0);
                    redisUtil.remove(key);
                    log.info("激活成功！");
                    resultMap.put("result_msg", "激活成功！");
                } else {
                    resultMap.put("result_msg", "邮箱不匹配！");
                }
            }
        }
        return resultMap;
    }

    @PostMapping("/getUserByPage/{pageNumber}")
    @ResponseBody
    public List<User> getUserByPage(@PathVariable("pageNumber") Integer pageNumber) {
        List<User> list = userService.list();
        PageInfo<User> pageInfo = new PageInfo<>(list);
        return list;
    }
}
    